home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 January / macpower199701.bin / AMUG / Programming_10 / WASTE 1.3a1.sit / WASTE 1.3a1 Distribution / WASTE 1.3a1 / WEObjects.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-23  |  10.0 KB  |  392 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    WEObjects.c
  3.  *
  4.  *    WASTE PROJECT
  5.  *  Embedded Objects
  6.  *
  7.  *  Copyright (c) 1993-1996 Marco Piovanelli
  8.  *    All Rights Reserved
  9.  *
  10.  *  C port by Dan Crevier
  11.  *
  12.  */
  13.  
  14.  
  15. #include "WASTEIntf.h"
  16.  
  17. #if WASTE_OBJECTS
  18.  
  19. // static variables
  20.  
  21. static WEOHTableHandle _weGlobalObjectHandlerTable;
  22.  
  23. pascal FlavorType WEGetObjectType(WEObjectDescHandle hObjectDesc)
  24. {
  25.     return (*hObjectDesc)->objectType;
  26. }
  27.  
  28. pascal Handle WEGetObjectDataHandle(WEObjectDescHandle hObjectDesc)
  29. {
  30.     return (*hObjectDesc)->objectDataHandle;
  31. }
  32.  
  33. pascal Point WEGetObjectSize(WEObjectDescHandle hObjectDesc)
  34. {
  35.     return (*hObjectDesc)->objectSize;
  36. }
  37.  
  38. pascal WEHandle WEGetObjectOwner(WEObjectDescHandle hObjectDesc)
  39. {
  40.     return (*hObjectDesc)->objectOwner;
  41. }
  42.  
  43. pascal SInt32 WEGetObjectRefCon(WEObjectDescHandle hObjectDesc)
  44. {
  45.     return (*hObjectDesc)->objectRefCon;
  46. }
  47.  
  48. pascal void WESetObjectRefCon(WEObjectDescHandle hObjectDesc, SInt32 refCon)
  49. {
  50.     (*hObjectDesc)->objectRefCon = refCon;
  51. }
  52.  
  53. pascal SInt32 _WELookupObjectType(FlavorType objectType, WEOHTableHandle hTable)
  54. {
  55.     // look for a WEOHTableElement record for the specified object kind
  56.     // in the given object handler table
  57.  
  58.     SInt32 nEntries, index;
  59.     WEOHTablePtr pTable;
  60.  
  61.     // do nothing if the Object Handler Table has not been inited yet
  62.     if (hTable == nil)
  63.         return kUnknownObjectType;
  64.  
  65.     // calculate entry count
  66.     nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  67.  
  68.     // scan the Object Handler Table looking for a type match
  69.     pTable = *hTable;
  70.     for ( index = 0; index < nEntries; index++ )
  71.     {
  72.         if (pTable->objectType == objectType)
  73.             return index;
  74.         pTable++;
  75.     }
  76.  
  77.     return kUnknownObjectType;
  78. }
  79.  
  80. pascal OSErr _WEGetIndObjectType(SInt32 index, FlavorType *objectType, WEHandle hWE)
  81. {
  82.     WEOHTableHandle hTable;
  83.     SInt32 nEntries;
  84.  
  85.     *objectType = 0L;
  86.  
  87.     // index must be non-negative
  88.     if (index < 0)
  89.         return weUnknownObjectTypeErr;
  90.  
  91.     // calculate number of entries in the instance-specific handler table
  92.     nEntries = 0;
  93.     hTable = (*hWE)->hObjectHandlerTable;
  94.     if (hTable != nil)
  95.         nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  96.  
  97.     // low indices refer to the instance-specific handler table
  98.     if (index < nEntries)
  99.     {
  100.         *objectType = (*hTable)[index].objectType;
  101.         return noErr;
  102.     }
  103.     // indices above that refer to the global handler table
  104.     index -= nEntries;
  105.  
  106.     // calculate number of entries in the global handler table
  107.     nEntries = 0;
  108.     hTable = _weGlobalObjectHandlerTable;
  109.     if (hTable != nil)
  110.         nEntries = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  111.  
  112.     // return an error code if index is too large
  113.     if (index >= nEntries)
  114.         return weUnknownObjectTypeErr;
  115.  
  116.     *objectType = (*hTable)[index].objectType;
  117.  
  118.     return noErr;
  119. }
  120.  
  121. pascal OSErr _WENewObject(FlavorType objectType, Handle objectDataHandle, WEHandle hWE,
  122.                     WEObjectDescHandle *hObjectDesc)
  123. {
  124.     WEObjectDescPtr pDesc;
  125.     WEOHTableHandle hTable;
  126.     SInt32 index;
  127.     OSErr err;
  128.  
  129.     *hObjectDesc = nil;
  130.  
  131.     // first look up the specified object type in the instance-specific handler table
  132.     hTable = (*hWE)->hObjectHandlerTable;
  133.     if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  134.     {
  135.         // no match: try with the global handler table
  136.         hTable = _weGlobalObjectHandlerTable;
  137.         if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  138.             hTable = nil;
  139.     }
  140.  
  141.     // create a new relocatable block to hold the object descriptor
  142.     if ((err = _WEAllocate(sizeof(WEObjectDesc), kAllocClear, (Handle *)hObjectDesc)) != noErr)
  143.         return err;
  144.  
  145.     // lock it down
  146.     HLock((Handle) *hObjectDesc);
  147.     pDesc = (WEObjectDescPtr) **hObjectDesc;
  148.  
  149.     // fill in the object descriptor
  150.     pDesc->objectType = objectType;
  151.     pDesc->objectDataHandle = objectDataHandle;
  152.     pDesc->objectSize.v = kDefaultObjectHeight;
  153.     pDesc->objectSize.h = kDefaultObjectWidth;
  154.     pDesc->objectTable = hTable;
  155.     pDesc->objectIndex = index;
  156.     pDesc->objectOwner = hWE;
  157.  
  158.     if (hTable != nil)
  159.     {
  160.         WENewObjectUPP newHandler = (*hTable)[index].newHandler;
  161.         pDesc->objectRefCon = (*hTable)[index].refCon;
  162.  
  163.         // call the new handler, if any
  164.         if (newHandler != nil)
  165.         {
  166.             if ((err = CallWENewObjectProc(&pDesc->objectSize, *hObjectDesc, newHandler)) != noErr)
  167.             {
  168.                 _WEForgetHandle((Handle *) hObjectDesc);
  169.                 return err;
  170.             }
  171.         }
  172.     }
  173.  
  174.     // unlock the object descriptor
  175.     HUnlock((Handle) *hObjectDesc);
  176.  
  177.     // clear result code
  178.     return noErr;
  179. }
  180.  
  181. pascal OSErr _WEFreeObject(WEObjectDescHandle hObjectDesc)
  182. {
  183.     WEObjectDescPtr pDesc;
  184.     OSErr err = noErr;
  185.  
  186.     // sanity check: do nothing if we have a null descriptor handle
  187.     if (hObjectDesc == nil)
  188.         return nilHandleErr;
  189.  
  190.     // lock the descriptor record
  191.     HLock((Handle)hObjectDesc);
  192.     pDesc = *hObjectDesc;
  193.  
  194.     if (pDesc->objectTable != nil)
  195.     {
  196.         WEDisposeObjectUPP freeHandler = (*pDesc->objectTable)[pDesc->objectIndex].freeHandler;
  197.  
  198.         // call the dispose handler, if any
  199.         if (freeHandler != nil)
  200.         {
  201.             err = CallWEDisposeObjectProc(hObjectDesc, freeHandler);
  202.             pDesc->objectDataHandle = nil;
  203.         }
  204.     }
  205.  
  206.     // if object kind is unknown or there's no custom dispose handler, use DisposeHandle
  207.     _WEForgetHandle(&pDesc->objectDataHandle);
  208.  
  209.     // finally, dispose of the object descriptor itself
  210.     DisposeHandle((Handle)hObjectDesc);
  211.  
  212.     return err;
  213. }
  214.  
  215. pascal OSErr _WEDrawObject(WEObjectDescHandle hObjectDesc)
  216. {
  217.     WEObjectDescPtr pDesc;
  218.     Rect destRect;
  219.     PenState state;
  220.     Boolean saveDescLock;
  221.     OSErr err = noErr;
  222.  
  223.     // lock the object descriptor
  224.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  225.     pDesc = *hObjectDesc;
  226.  
  227.     // get current pen state
  228.     // state.pnLoc has already been set to the bottom left of the rectangle to draw
  229.     GetPenState(&state);
  230.  
  231.     // calculate the new pen position
  232.     state.pnLoc.h += pDesc->objectSize.h;
  233.  
  234.     // calculate the destination rectangle
  235.     * (SInt32 *) (&topLeft(destRect)) = DeltaPoint(state.pnLoc, pDesc->objectSize);
  236.     botRight(destRect) = state.pnLoc;
  237.  
  238.     if (pDesc->objectTable != nil)
  239.     {
  240.         WEDrawObjectUPP drawHandler = (*pDesc->objectTable)[pDesc->objectIndex].drawHandler;
  241.  
  242.         // call the drawing handler, if any
  243.         if (drawHandler != nil)
  244.             err = CallWEDrawObjectProc(&destRect, hObjectDesc, drawHandler);
  245.     }
  246.     else
  247.     {
  248.         // if this object kind was not registered, draw an empty frame
  249.         PenNormal();
  250.         FrameRect(&destRect);
  251.     }
  252.  
  253.     // restore original pen state, advancing the pen position by the object width
  254.     SetPenState(&state);
  255.  
  256.     // unlock the object descriptor
  257.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  258.  
  259.     return err;
  260. }
  261.  
  262. pascal Boolean _WEClickObject(Point hitPt, EventModifiers modifiers, UInt32 clickTime,
  263.                                 WEObjectDescHandle hObjectDesc)
  264. {
  265.     WEObjectDescPtr pDesc;
  266.     Boolean saveDescLock;
  267.     Boolean clickHandled = false;
  268.  
  269.     // lock the object descriptor
  270.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  271.     pDesc = *hObjectDesc;
  272.  
  273.     if (pDesc->objectTable != nil)
  274.     {
  275.         WEClickObjectUPP clickHandler = (*pDesc->objectTable)[pDesc->objectIndex].clickHandler;
  276.  
  277.         // call the click handler, if any
  278.         if (clickHandler != nil)
  279.             clickHandled = CallWEClickObjectProc(hitPt, modifiers, clickTime, hObjectDesc, clickHandler);
  280.     }
  281.  
  282.     // unlock the object descriptor
  283.     _WESetHandleLock((Handle)hObjectDesc, saveDescLock);
  284.  
  285.     return clickHandled;
  286. }
  287.  
  288. pascal OSErr _WEStreamObject(SInt16 destKind, FlavorType *theType,
  289.                 Handle *theData, Boolean *canDisposeData, WEObjectDescHandle hObjectDesc)
  290. {
  291.     WEObjectDescPtr pDesc;
  292.     Boolean saveDescLock;
  293.     OSErr err = weNotHandledErr;
  294.  
  295.     *canDisposeData = true;
  296.  
  297.     // lock the object descriptor
  298.     saveDescLock = _WESetHandleLock((Handle)hObjectDesc, true);
  299.     pDesc = *hObjectDesc;
  300.  
  301.     if (pDesc->objectTable != nil)
  302.     {
  303.         WEStreamObjectUPP streamHandler = (*pDesc->objectTable)[pDesc->objectIndex].streamHandler;
  304.  
  305.         // call the stream handler, if any
  306.         if (streamHandler != nil)
  307.             err = CallWEStreamObjectProc(destKind, theType, *theData, hObjectDesc, streamHandler);
  308.     }
  309.  
  310.     if (err == weNotHandledErr)
  311.     {
  312.         // default streaming behavior
  313.         _WEForgetHandle(theData);
  314.         *canDisposeData = false;
  315.         *theType = pDesc->objectType;
  316.         *theData = pDesc->objectDataHandle;
  317.         err = noErr;
  318.     }
  319.  
  320.     // unlock the object descriptor
  321.     _WESetHandleLock((Handle) hObjectDesc, saveDescLock);
  322.  
  323.     return err;
  324. }
  325.  
  326. pascal OSErr WEInstallObjectHandler(FlavorType objectType, WESelector handlerSelector,
  327.                 UniversalProcPtr handler, WEHandle hWE)
  328. {
  329.     WEOHTableHandle hTable;
  330.     SInt32 index;
  331.     WEOHTableElement element;
  332.     OSErr err;
  333.  
  334.     // if hWE is nil, install the handler in the global handler table,
  335.     // otherwise install the handler in the instance-specific handler table
  336.     if (hWE == nil)
  337.         hTable = _weGlobalObjectHandlerTable;
  338.     else
  339.         hTable = (*hWE)->hObjectHandlerTable;
  340.  
  341.     // create the handler table, if it doesn't exist
  342.     if (hTable == nil)
  343.     {
  344.         hTable = (WEOHTableHandle) NewHandle(0);
  345.         if ((err = MemError()) != noErr)
  346.             return err;
  347.         if (hWE == nil)
  348.             _weGlobalObjectHandlerTable = hTable;
  349.         else
  350.             (*hWE)->hObjectHandlerTable = hTable;
  351.     }
  352.  
  353.     // look for the entry corresponding to the specified object type
  354.     if ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType)
  355.     {
  356.         BLOCK_CLR(element);
  357.         element.objectType = objectType;
  358.  
  359.         // previously unknown object type: append a new entry at the end of the handler table
  360.         index = GetHandleSize((Handle) hTable) / sizeof(WEOHTableElement);
  361.         if ((err = _WESplice((Handle) hTable, &element, sizeof(element), -1)) != noErr)
  362.             return err;
  363.     }
  364.  
  365.     // install the handler
  366.     return _WESetField(_weObjectHandlerSelectorTable, handlerSelector, (SInt32 *) &handler, *hTable + index);
  367. }
  368.  
  369. pascal OSErr WEGetObjectHandler(FlavorType objectType, WESelector handlerSelector,
  370.                 UniversalProcPtr *handler, WEHandle hWE)
  371. {
  372.     WEOHTableHandle hTable;
  373.     SInt32 index;
  374.  
  375.     // if hWE is nil, look for the handler in the global handler table,
  376.     // otherwise look in the instance-specific handler table
  377.     if (hWE == nil)
  378.         hTable = _weGlobalObjectHandlerTable;
  379.     else
  380.         hTable = (*hWE)->hObjectHandlerTable;
  381.  
  382.     // first make sure the handler table exists
  383.     // then check to see if an entry for the specified object type is present
  384.     if ((hTable == nil) || ((index = _WELookupObjectType(objectType, hTable)) == kUnknownObjectType))
  385.         return weUnknownObjectTypeErr;
  386.  
  387.     // return the address of the specified handler
  388.     return _WEGetField(_weObjectHandlerSelectorTable, handlerSelector, (SInt32 *) handler, *hTable + index);
  389. }
  390.  
  391. #endif  // WASTE_OBJECTS
  392.